package com.plus.config.dataEncry;


import com.plus.entity.customEntity.Response;
import com.plus.entity.customEntity.ResponseSign;
import com.plus.utils.AESUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

/**
 * @Description：后置响应加密处理逻辑
 */
@ControllerAdvice
@Slf4j
public class MyResponseBodyAdvice implements ResponseBodyAdvice {

    @Override
    public boolean supports(MethodParameter methodParameter, Class aClass) {
        SafetyProcess process = methodParameter.getMethodAnnotation(SafetyProcess.class);
        //如果带有安全注解且标记为加密，测进行加密操作
        return null != process && process.responeEncode();
    }

    /**
     * 约定，响应方加密算法：
     * 1.对源数据转换成json字符串
     * 2.然后调用aes加密
     * @param o
     * @param methodParameter
     * @param mediaType
     * @param aClass
     * @param serverHttpRequest
     * @param serverHttpResponse
     * @return
     */
    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class aClass,
                                  ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        Object data = null;
        //如果是rest接口统一封装返回对象
        if (o instanceof Response) {
            Response res = (Response) o;
            //如果返回成功
            if (res.isOk()) {
                data = res.getData();
            } else {
                return o;
            }
        }
        else  if (o instanceof ResponseSign) {
            Object datas = ((ResponseSign<?>) o).getData();
            //加密
            String e = AESUtil.encode(datas);
            ResponseSign mp = new ResponseSign();
            mp.setData(e);
            mp.setMessage(((ResponseSign<?>) o).getMessage());
            mp.setCode(((ResponseSign<?>) o).getCode());
            mp.setSign(((ResponseSign<?>) o).getSign());
            mp.setTimestamp(((ResponseSign<?>) o).getTimestamp());
            mp.setVersion(((ResponseSign<?>) o).getVersion());

            return mp;
        }
        else {
            data = o;
        }
        //加密
        return Response.success(AESUtil.encode(data));
    }
}
